import {
  Injectable,
  OnApplicationBootstrap,
  OnApplicationShutdown,
} from '@nestjs/common';
import * as dgram from 'dgram';
import { Socket } from 'dgram';

// UDP数据类型枚举
export enum UdpDataType {
  TEXT = 'text',
  STATUS = 'status',
  SENSOR = 'sensor',
  GAME = 'game',
  POSITION = 'position',
}

// 通用UDP消息接口
export interface UdpMessage {
  type: UdpDataType;
  timestamp: number;
  data: any;
}

// 传感器数据接口
export interface SensorData {
  temperature: number;
  humidity: number;
  pressure: number;
  deviceId: string;
}

// 游戏数据接口
export interface GameData {
  playerId: string;
  x: number;
  y: number;
  action: string;
  score: number;
}

// 状态数据接口
export interface StatusData {
  deviceId: string;
  status: 'online' | 'offline' | 'busy' | 'idle';
  batteryLevel?: number;
  signalStrength?: number;
}

@Injectable()
export class UdpService
  implements OnApplicationBootstrap, OnApplicationShutdown
{
  private server: Socket;
  private readonly host = '0.0.0.0'; // 监听所有网络接口
  private readonly port = 3001; // 您可以根据需要调整端口

  // 存储客户端信息
  private clients = new Map<
    string,
    { address: string; port: number; lastSeen: number }
  >();

  // 存储传感器数据历史
  private sensorDataHistory: SensorData[] = [];

  // 存储游戏状态
  private gameState = new Map<string, GameData>();

  async onApplicationBootstrap() {
    this.startServer();
    // 启动清理过期客户端的定时任务
    setInterval(() => this.cleanupInactiveClients(), 60000); // 每分钟清理一次
  }

  async onApplicationShutdown() {
    this.closeServer();
  }

  private startServer() {
    this.server = dgram.createSocket('udp4');

    this.server.on('error', (err) => {
      console.error(`UDP服务器错误: ${err.stack}`);
      this.server.close();
    });

    this.server.on('message', (msg, rinfo) => {
      const clientKey = `${rinfo.address}:${rinfo.port}`;

      // 更新客户端最后活跃时间
      this.clients.set(clientKey, {
        address: rinfo.address,
        port: rinfo.port,
        lastSeen: Date.now(),
      });

      try {
        // 尝试解析JSON消息
        const message: UdpMessage = JSON.parse(msg.toString());
        console.log(
          `收到来自 ${rinfo.address}:${rinfo.port} 的${message.type}类型消息`,
        );

        // 根据消息类型处理
        this.handleMessageByType(message, rinfo);
      } catch (e) {
        // 如果不是JSON，则作为普通文本处理
        console.log(
          `收到来自 ${rinfo.address}:${rinfo.port} 的文本消息: ${msg}`,
        );
        // 回显文本消息
        this.server.send(`收到您的消息: ${msg}`, rinfo.port, rinfo.address);
      }
    });

    this.server.on('listening', () => {
      const address = this.server.address();
      console.log(`UDP服务器正在监听 ${address.address}:${address.port}`);
      console.log(
        '支持的数据类型: text, status, sensor, game, position, metadata',
      );
    });

    this.server.on('close', () => {
      console.log('UDP服务器已关闭');
    });

    this.server.bind(this.port, this.host);
  }

  private handleMessageByType(message: UdpMessage, rinfo: dgram.RemoteInfo) {
    switch (message.type) {
      case UdpDataType.STATUS:
        this.handleStatusData(message.data as StatusData, rinfo);
        break;
      case UdpDataType.SENSOR:
        this.handleSensorData(message.data as SensorData, rinfo);
        break;
      case UdpDataType.GAME:
        this.handleGameData(message.data as GameData, rinfo);
        break;
      case UdpDataType.POSITION:
        this.handlePositionData(message.data, rinfo);
        break;
      case UdpDataType.TEXT:
      default:
        this.server.send(
          JSON.stringify({
            type: 'response',
            timestamp: Date.now(),
            data: { received: message.data },
          }),
          rinfo.port,
          rinfo.address,
        );
        break;
    }
  }

  private handleStatusData(data: StatusData, rinfo: dgram.RemoteInfo) {
    console.log(`设备 ${data.deviceId} 状态更新: ${data.status}`);

    // 广播设备状态更新给所有客户端
    this.broadcastMessage(
      JSON.stringify({
        type: 'status_update',
        timestamp: Date.now(),
        data,
      }),
    );

    // 确认收到状态更新
    this.server.send(
      JSON.stringify({
        type: 'status_ack',
        timestamp: Date.now(),
        data: { deviceId: data.deviceId, received: true },
      }),
      rinfo.port,
      rinfo.address,
    );
  }

  private handleSensorData(data: SensorData, rinfo: dgram.RemoteInfo) {
    // 存储传感器数据（限制历史数据量）
    this.sensorDataHistory.push(data);
    if (this.sensorDataHistory.length > 1000) {
      this.sensorDataHistory.shift();
    }

    console.log(
      `收到设备 ${data.deviceId} 的传感器数据: 温度=${data.temperature}°C, 湿度=${data.humidity}%`,
    );

    // 可以在这里添加阈值报警逻辑
    if (data.temperature > 30) {
      console.warn(
        `⚠️  温度警告: ${data.deviceId} 温度过高 (${data.temperature}°C)`,
      );
    }

    // 确认收到传感器数据
    this.server.send(
      JSON.stringify({
        type: 'sensor_ack',
        timestamp: Date.now(),
        data: { deviceId: data.deviceId, count: this.sensorDataHistory.length },
      }),
      rinfo.port,
      rinfo.address,
    );
  }

  private handleGameData(data: GameData, rinfo: dgram.RemoteInfo) {
    // 更新游戏状态
    this.gameState.set(data.playerId, data);

    // 广播游戏状态给所有客户端（游戏同步）
    this.broadcastMessage(
      JSON.stringify({
        type: 'game_update',
        timestamp: Date.now(),
        data,
      }),
    );
  }

  private handlePositionData(data: any, rinfo: dgram.RemoteInfo) {
    console.log(`收到位置数据: ${JSON.stringify(data)}`);

    // 广播位置更新
    this.broadcastMessage(
      JSON.stringify({
        type: 'position_update',
        timestamp: Date.now(),
        data,
      }),
    );
  }

  private cleanupInactiveClients() {
    const now = Date.now();
    const inactiveThreshold = 5 * 60 * 1000; // 5分钟不活跃则清理

    for (const [key, client] of this.clients.entries()) {
      if (now - client.lastSeen > inactiveThreshold) {
        this.clients.delete(key);
        console.log(`清理不活跃客户端: ${key}`);
      }
    }
  }

  private closeServer() {
    if (this.server) {
      this.server.close(() => {
        console.log('UDP服务器已关闭');
      });
    }
  }

  // 发送消息到指定客户端
  sendMessageToClient(
    address: string,
    port: number,
    message: string,
  ): Promise<number> {
    return new Promise((resolve, reject) => {
      this.server.send(message, port, address, (err, bytes) => {
        if (err) {
          reject(err);
        } else {
          resolve(bytes);
        }
      });
    });
  }

  // 发送JSON消息到指定客户端
  sendJsonMessageToClient(
    address: string,
    port: number,
    message: UdpMessage,
  ): Promise<number> {
    return this.sendMessageToClient(address, port, JSON.stringify(message));
  }

  // 广播消息到所有已知客户端
  broadcastMessage(message: string): Promise<void> {
    return Promise.all(
      Array.from(this.clients.values()).map((client) =>
        this.sendMessageToClient(client.address, client.port, message),
      ),
    ).then(() => {});
  }

  // 广播JSON消息
  broadcastJsonMessage(message: UdpMessage): Promise<void> {
    return this.broadcastMessage(JSON.stringify(message));
  }

  // 获取所有连接的客户端
  getConnectedClients() {
    return Array.from(this.clients.entries());
  }

  // 获取传感器数据历史（最近N条）
  getSensorDataHistory(limit: number = 100) {
    return this.sensorDataHistory.slice(-limit);
  }

  // 获取当前游戏状态
  getGameState() {
    return Array.from(this.gameState.entries());
  }
}
